package com.yanghui.lingyue.functions.ktBase

import com.icedata.sika.bridge.*
import com.icedata.sika.core.CommandProcessor
import com.icedata.sika.core.Sika
import com.icedata.sika.database.Column
import com.icedata.sika.database.DataNotFoundException
import com.icedata.sika.database.Table
import com.yanghui.lingyue.bot.Bot
import com.yanghui.lingyue.data.Command
import com.yanghui.lingyue.data.Operation
import com.yanghui.lingyue.functions.AbstractFunction
import com.yanghui.lingyue.utils.functionUtils.FunctionUtils
import com.yanghui.lingyue.utils.timeUtils.TimeUtils
import java.sql.Timestamp
import java.util.*

object DriftBottle : AbstractFunction() {
    override val name: String = "DriftBottle"

    override suspend fun parse(event: SikaEvent, sika: Sika): LinkedList<Command> {
        val command = LinkedList<Command>()
        if (event is SikaUserEvent) return command
        event as SikaGroupEvent
        if (!FunctionUtils.atBot(event)) return command
        if (!FunctionUtils.checkValid(event)) return command
        if (event.sendGroup.id !in enableGroup) return command

        val messageContent = FunctionUtils.extractPlainMessage(event).trim()
        if (messageContent.startsWith("丢瓶子")) {
            command.add(Command(event, "$name -Add -Local", ""))
        } else if (messageContent.startsWith("捡瓶子")) {
            command.add(Command(event, "$name -Get -Local", ""))
        } else if (messageContent.startsWith("好瓶子")) {
            command.add(
                Command(
                    event,
                    "$name -Like ${messageContent.replace("好瓶子", "").trim()}",
                    ""
                )
            )
        }
        return command
    }

    override suspend fun execute(command: Command, sika: Sika): CommandProcessor.Result {
        val instructionList = command.instruction.split(" ")
        val messageContent =
            FunctionUtils.extractPlainMessage(command.event as SikaGroupEvent)

        val operation = Operation(command)
        Bot.sikaCore.databaseInsert(operation)
        when (instructionList[1]) {
            "-Add" -> when (instructionList[2]) {
                "-Local" -> {
                    val content = messageContent.replace("丢瓶子", "")
                    if (hasSameBottle(content)) return CommandProcessor.Result.ADOPT
                    addBottle(Bottle().apply {
                        operationID = operation.operationID
                        senderID = operation.userID
                        groupID = operation.groupID
                        restPick = 2
                        sendTime = operation.time
                        getLike = 0
                        this.content = content.trim()
                    })
                    command.sendGroup?.sendMessage("收到")
                }
                "-Global" -> {
                    val content = messageContent.replace("丢大瓶子", "")
                    if (hasSameBottle(content)) return CommandProcessor.Result.ADOPT
                    addBottle(Bottle().apply {
                        operationID = operation.operationID
                        senderID = operation.userID
                        groupID = 0
                        restPick = 2
                        sendTime = operation.time
                        getLike = 0
                        this.content = content.trim()
                    })
                    command.sendGroup?.sendMessage("收到")
                }
            }
            "-Get" -> {
                when (instructionList[2]) {
                    "-Local" -> {
                        val bottle = getBottle(command.sendGroup!!.id)
                        bottle ?: run {
                            command.sendGroup?.sendMessage("这片海里，什么都没有呢")
                            return CommandProcessor.Result.ADOPT
                        }
                        val builder = SikaMessageChainBuilder()
                        builder.add(SikaAtMessage(command.sender.id))
                        builder.add(
                            "\n你收到了一条${
                                TimeUtils.getTimeDiff(
                                    bottle.sendTime.time,
                                    Date().time
                                )
                            }前的漂流瓶，编号${bottle.operationID}\n${bottle.content}"
                        )
                        val pickBottle = PickBottle(
                            operation.operationID,
                            command.sender.id,
                            bottle.operationID
                        )
                        operation.let {
                            it.target = bottle.operationID
                            Bot.sikaCore.databaseUpdate(operation)
                        }
                        Bot.sikaCore.databaseInsert(pickBottle)
                        command.sendGroup?.sendMessage(builder)
                    }
                    "-Global" -> {
                        val bottle = getBottle(0)
                        bottle ?: run {
                            command.sendGroup?.sendMessage("这片海里，什么都没有呢")
                            return CommandProcessor.Result.ADOPT
                        }
                        val builder = SikaMessageChainBuilder()
                        builder.add(SikaAtMessage(command.sender.id))
                        builder.add(
                            "\n你收到了一条${
                                TimeUtils.getTimeDiff(
                                    bottle.sendTime.time,
                                    Date().time
                                )
                            }前的漂流瓶，编号${bottle.operationID}\n${bottle.content}"
                        )
                        operation.let {
                            it.target = bottle.operationID
                            Bot.sikaCore.databaseUpdate(operation)
                        }
                        command.sendGroup?.sendMessage(builder)
                    }
                }
            }
            "-Like" -> {
                if (command.instruction.replace("$name -Like", "").trim().isEmpty()) {
                    val sql = "SELECT TOP 1 pickBottleID FROM PickDriftBottle " +
                            "WHERE userID = ? " +
                            "ORDER BY operationID DESC"
                    val statement = Bot.sikaCore.getStatement(sql)
                    statement.setLong(1, command.event.sender.id)
                    val resultSet = statement.executeQuery()
                    resultSet.next()
                    val bottleID = resultSet.getLong(1)
                    val bottle = Bot.sikaCore.databaseSelect<Bottle>(bottleID)
                    bottle.getLike++
                    Bot.sikaCore.databaseUpdate(bottle)
                } else {
                    val bottleID: Long
                    try {
                        bottleID = command.instruction.replace("$name -Like", "").trim().toLong()
                        val bottle = Bot.sikaCore.databaseSelect<Bottle>(bottleID)
                        bottle.getLike++
                        Bot.sikaCore.databaseUpdate(bottle)
                    } catch (e: NumberFormatException) {
                        command.sendGroup?.sendMessage("你输入的好像不是数字哦")
                        return CommandProcessor.Result.ADOPT
                    } catch (e: DataNotFoundException) {
                        command.sendGroup?.sendMessage("你输入的好像不是这个瓶子的ID哦")
                        return CommandProcessor.Result.ADOPT
                    }
                }
                command.sendGroup?.sendMessage("点赞成功")
            }
        }
        return CommandProcessor.Result.ADOPT
    }

    private fun addBottle(bottle: Bottle) {
        Bot.sikaCore.databaseInsert(bottle)
    }

    private fun getBottle(groupID: Long): Bottle? {
        val sql = "SELECT TOP 1 * From DriftBottle " +
                "WHERE groupID = ? AND restPick > 0 " +
                "ORDER BY newid()"
        val statement = Bot.sikaCore.getStatement(sql)
        statement.setLong(1, groupID)
        val result = statement.executeQuery()
        return if (result.next()) {
            val bottle = Bottle().apply {
                operationID = result.getLong("operationID")
                senderID = result.getLong("senderID")
                this.groupID = result.getLong("groupID")
                restPick = (result.getShort("restPick") - 1).toShort()
                sendTime = result.getTimestamp("sendTime")
                getLike = result.getInt("getLike")
                content = result.getNString("bottleContent")
            }
            Bot.sikaCore.databaseUpdate(bottle)
            return bottle
        } else null
    }

    private fun hasSameBottle(content: String): Boolean {
        return false
    }

    @Table("DriftBottle", "", "operationID")
    class Bottle {
        @Column("operationID")
        var operationID: Long = 0

        @Column("senderID")
        var senderID: Long = 0

        @Column("bottleContent")
        var content: String = ""

        @Column("groupID")
        var groupID: Long = 0

        @Column("restPick")
        var restPick: Short = 2

        @Column("sendTime")
        var sendTime: Timestamp = Timestamp(0)

        @Column("getLike")
        var getLike: Int = 0
    }

    @Table("PickDriftBottle", "", "operationID")
    class PickBottle(
        @Column("operationID")
        var operationID: Long,

        @Column("userID")
        var userID: Long,

        @Column("pickBottleID")
        var pickBottleID: Long
    ) {
        constructor() : this(0, 0, 0)
    }
}

object DriftBottleGlobal : AbstractFunction() {
    override val name: String = "DriftBottle"

    override suspend fun parse(event: SikaEvent, sika: Sika): LinkedList<Command> {
        val command = LinkedList<Command>()
        if (event is SikaUserEvent) return command
        event as SikaGroupEvent
        if (!FunctionUtils.atBot(event)) return command
        if (!FunctionUtils.checkValid(event)) return command
        if (event.sendGroup.id !in enableGroup) return command

        val messageContent = FunctionUtils.extractPlainMessage(event).trim()
        if (messageContent.startsWith("丢大瓶子")) {
            command.add(Command(event, "${DriftBottle.name} -Add -Global", ""))
        } else if (messageContent.startsWith("捡大瓶子")) {
            command.add(Command(event, "${DriftBottle.name} -Get -Global", ""))
        }
        return command
    }

    override suspend fun execute(command: Command, sika: Sika): CommandProcessor.Result {
        TODO("Nothing To Do")
    }

    override fun filter(command: Command): Boolean {
        return false
    }

}